第 4 步 - 创建选择小组件的交互处理程序

在本教程中,您将创建用户能滚动包含在Widget Grid List Box 中的小组件列表的应用程序,并且用户能从该列表选择Widget Item Prefab 表示的小组件。3D 网格列表框 (Grid List Box 3D) 节点提供能在 Kanzi Studio 工程中设置的水平滚动,但您需要定义处理小组件选择的应用程序逻辑。

在该教程的这一步骤中,您将实现在用户点击小组件时处理小组件项选择的功能:

要创建选择小组件的交互处理程序:

  1. ProgrammerTutorialApplication 类中的 onProjectLoaded() 函数后,实现在Widget Grid List Box 中选择小组件的事件处理程序。使用选定小组件的索引,检索Widget Grid List Box 节点的选定小组件。
    class ProgrammerTutorialApplication : public ExampleApplication
    {
    ...
    private: 
    
        //来自Widget Grid List Box 的 ListBox.ItemSelected 消息处理程序。
        //将选择的列表框项移到前面。
        void onListBoxItemSelected(ListBoxConcept::ItemSelectedMessageArguments& messageArguments)
        {
            //从消息参数中检索选定列表框项的索引。
            optional<size_t> selectedItemIndex = messageArguments.getSelectedItemIndex();
    
            if (selectedItemIndex)
            {
                //移除旧回放,以重置值。
                //在该教程的下一步实现此函数。
                removePlaybacks();
    
                //按其索引检索选定列表框项。
                m_selectedItem = m_widgetList->getItem(*selectedItemIndex);
    	 ...
            }
        }
    };
  2. 目标动画重定位摄像机。动画使用节点的当前变换,并动画化为另一个节点定义的另一个变换。
    现在,存储的摄像机变换会被更新为选定小组件的变换。
    为摄像机创建动画,并开始动画。
    void onListBoxItemSelected(ListBoxConcept::ItemSelectedMessageArguments& messageArguments)
    {
    ...
        if (selectedItemIndex)
        {
            ...
            //计算摄像机动画目标节点的新值,并开始动画。
            {
                //获取当前变换。
                Matrix4x4 selectedItemTransformation = m_selectedItem->getFinalTransformation();
                //获取摄像机的相对变换目标位置。
                SRTValue3D transformationTarget = m_cameraTransformationTarget;
                //将选定项的位置添加到目标摄像机变换中。
                transformationTarget.setTranslation(selectedItemTransformation.getTranslation() - transformationTarget.getTranslation());
                //为摄像机创建动画。
                m_cameraAnimation = FromToAnimation<SRTValue3D, LinearEasingFunction>::create(getDomain(), chrono::seconds(1), nullopt, transformationTarget);
    
                //开始动画。
                PropertyAnimationTimelineSharedPtr cameraTimeline = PropertyAnimationTimeline::create(getDomain(), ".", Node3D::RenderTransformationProperty, m_cameraAnimation);
                SceneGraphTimelinePlaybackContext cameraContext(*m_camera);
                m_cameraPlayback = cameraTimeline->createPlayback(cameraContext);
                getDomain()->getRootTimelineClock()->addTimelinePlayback(m_cameraPlayback);
            }
        }
    ...
    }
  3. 现在,摄像机 (Camera) 动画的变换目标已更新,您可以为选定小组件初始化高亮动画。高亮动画使小组件绕其 x 轴从固定值 0 到 60 度旋转,并在 onProjectLoaded() 函数中定义。
    void onListBoxItemSelected(ListBoxConcept::ItemSelectedMessageArguments& messageArguments)
    {
    ...
        if (selectedItemIndex)
        {
       ... 
            //开始选定项的动画。
            PropertyAnimationTimelineSharedPtr selectedItemTimeline = PropertyAnimationTimeline::create(getDomain(), ".", Node3D::LayoutTransformationProperty, m_selectedItemAnimation);
            SceneGraphTimelinePlaybackContext selectedItemContext(*m_selectedItem);
            m_widgetHighlightPlayback = selectedItemTimeline->createPlayback(selectedItemContext);
            getDomain()->getRootTimelineClock()->addTimelinePlayback(m_widgetHighlightPlayback);
        }
    }
  4. 动画开始时禁用 Back button 输入。
    void onListBoxItemSelected(ListBoxConcept::ItemSelectedMessageArguments& messageArguments)
    {
    ...
        if (selectedItemIndex)
        {
        ... 
    
            //开始动画以禁用 Back button 输入。
            PropertyAnimationTimelineSharedPtr backButtonEnableTimeline = PropertyAnimationTimeline::create(getDomain(), ".", Button3D::HitTestableProperty, m_backButtonEnableAnimation);
            SceneGraphTimelinePlaybackContext backButtonEnableContext(*m_backButton);
            m_backButtonEnablePlayback = backButtonEnableTimeline->createPlayback(backButtonEnableContext);
            getDomain()->getRootTimelineClock()->addTimelinePlayback(m_backButtonEnablePlayback);
        }
    }
  5. Programmertutorial.WidgetDescription 属性获得小组件描述,并将 2D 文本块 (Text Block 2D) 节点的文本 (Text) 属性值设置为 Programmertutorial.WidgetDescription 属性的值,让包含面板的Widget Description Layer 显示在应用程序窗口右侧。
    void onListBoxItemSelected(ListBoxConcept::ItemSelectedMessageArguments& messageArguments)
    {
    ...
        if (selectedItemIndex)
        {
        ...
            //通过将Widget Description Layer 设置为可见,显示小组件描述。
            if (m_widgetDescriptionVisibilityPlayback)
            {
                getDomain()->getRootTimelineClock()->removeTimelinePlayback(*m_widgetDescriptionVisibilityPlayback);
                m_widgetDescriptionVisibilityPlayback.reset();
            }
    
            //将小组件描述设置成描述文本。描述取自小组件节点。
            string widgetDescription = m_selectedItem->getProperty(*m_widgetDescriptionPropertyType);
            m_widgetDescriptionTextBlock->setText(widgetDescription);
    
            //将Widget Description Layer 设置为可见。
            m_widgetDescriptionNode->setVisible(true);
        }
    }
  6. 填充小组件列表后,在 onProjectLoaded() 函数中注册 Widget Grid List Box 节点的 ItemSelectedMessage 消息处理程序。
    virtual void onProjectLoaded() KZ_OVERRIDE
    {
    ...
        //添加选择3D 网格列表框 (Grid List Box 3D) 项事件的消息处理程序。
        m_widgetList->addMessageHandler(GridListBox3D::ItemSelectedMessage, bind(&ProgrammerTutorialApplication::onListBoxItemSelected, this, placeholders::_1));		
    }
    当点击小组件时,应用程序使用指定的两个动画高亮显示小组件,让 Widget Description Layer 节点可见,并在 Widget Description Layer 中显示小组件描述。

< 上一步
下一步 >

另请参阅

编辑动画剪辑

创建关键帧动画

动画